package withouther.system.plugins.system.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.api.R;
import io.swagger.models.auth.In;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;
import withouther.system.core.base.BaseServiceImpl;
import withouther.system.core.util.page.PageQuery;
import withouther.system.core.util.page.PageUtils;

import withouther.system.plugins.system.entity.Menu;
import withouther.system.plugins.system.entity.Role;
import withouther.system.plugins.system.entity.RoleMenu;
import withouther.system.plugins.system.mapper.RoleMapper;
import withouther.system.plugins.system.service.MenuService;
import withouther.system.plugins.system.service.RoleMenuService;
import withouther.system.plugins.system.service.RoleService;

import javax.annotation.Resource;


@Service("roleService")
@CacheConfig(cacheNames = "role")
public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, Role> implements RoleService {


    @Resource
    private RoleMenuService roleMenuService;

    @Override
    @Cacheable
    public PageUtils queryPage(Map<String, Object> params) {
        String name = Convert.toStr(params.get("name"), "").trim();
        IPage<Role> page = this.page(
                new PageQuery<Role>().getPage(params),
                new QueryWrapper<Role>().like(StrUtil.isNotEmpty(name),"name", name)
        );
        return new PageUtils(page);
    }

    @Override
    @Cacheable(key = "'userId' + #p0")
    public List<Role> selectUserRoleListByUserId(Long userId) {
        return this.baseMapper.selectUserRoleListByUserId(userId);
    }

    @Override
    public Map<String, Object> getRoleMenus(Long id) {
//        List<Menu> menus = menuService.selectRoleMenusByRoleId(id);
        List<RoleMenu> roleMenus = roleMenuService.getRoleMenus(id);
        Set<Long> menuIds = roleMenus.stream().map(role -> role.getMid()).collect(Collectors.toSet());
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("menuIds", menuIds);
        return resultMap;
    }

    @Override
    @Transactional
    @CacheEvict(allEntries = true)
    public boolean addRole(Role role) {
        this.save(role);
        addRoleMenus(role);
        return true;
    }

    private Set<RoleMenu> addRoleMenus(Role role) {
        Set<RoleMenu> roleMenus = new HashSet<>();
        for (Menu menu : role.getMenus()) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRid(role.getId());
            roleMenu.setMid(menu.getId());
            roleMenus.add(roleMenu);
        }
        if (!roleMenus.isEmpty()) {
            roleMenuService.addRoleMenus(roleMenus);
        }
        return roleMenus;
    }

    private boolean deleteRoleByRid(Long rid) {
        roleMenuService.deleteRoleMenus(rid);
        return true;
    }
    @Override
    @Transactional
    @CacheEvict(allEntries = true)
    public boolean updateRole(Role role) {
        this.updateById(role);
        deleteRoleByRid(role.getId());
        addRoleMenus(role);
        return true;
    }

    @Override
    @Transactional
    @CacheEvict(allEntries = true)
    public boolean deleteRoles(List<Long> ids) {
        for (Long id : ids) {
            deleteRoleByRid(id);
            this.removeById(id);
        }
        return true;
    }

}